import { isUndefined, isNull, PagedList, PageParams } from "mmb";
import * as store_fanpb from "../grpc-client/service/store_fan_pb";
import { jsTimestampToPb, pbTimestampToJs } from "./helper";

import {
  getBgsStoreFanOpSafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";
import {
  StoreFan,
  UpsertStoreFanParams,
  UpdateStoreFanParams,
  StoreFanWithUserAndUserStat,
} from "./storeDeclareTypes";
import { getPub, makeTopicOfPub, wrapToMessage } from "../proxy/nsqProxy";

/****************************************************************************************/
/*                                   store_fan entity                                   */
/****************************************************************************************/
const topicOfUpsertStoreFan = "upsert-store_fan";

const StoreFanPbToObject = (pb: store_fanpb.StoreFanEntity): StoreFan => {
  return {
    storeFanId: `${pb.getId()}`,
    storeId: `${pb.getStoreId()}`,
    followerUserId: `${pb.getFollowerUserId()}`,
    beFollowed: pbTimestampToJs(pb.getBeFollowed()),
    aliasName: pb.getAliasName(),
    remark: pb.getRemark(),
  };
};

/****************************************************************************************/
/*                                   store_fan cmd                                      */
/****************************************************************************************/
export const upsertStoreFanMq = async ({
  storeId,
  followerUserId,
  beFollowed,
  aliasName,
}: UpsertStoreFanParams): Promise<boolean> => {
  return new Promise((resolve, reject) => {
    const topic = makeTopicOfPub(topicOfUpsertStoreFan);
    const msg = wrapToMessage({
      storeId: Number(storeId),
      followerUserId: Number(followerUserId),
      beFollowed: beFollowed,
      aliasName,
    });
    // console.log('publish upsertStoreFanMq =>', topic ,JSON.stringify(msg))
    getPub().publish(topic, msg, (err) => {
      if (err) {
        // console.log("upsertStoreFanMq err", err);
        reject(false);
      }
      // console.log("upsertStoreFanMq success");
      resolve(true);
    });
  });
};

export const upsertStoreFan = async ({
  storeId,
  followerUserId,
  beFollowed,
  aliasName,
}: UpsertStoreFanParams): Promise<StoreFan> => {
  const cl = getBgsStoreFanOpSafely();
  const req = new store_fanpb.UpsertStoreFanRequest();

  req.setStoreId(Number(storeId));
  req.setFollowerUserId(Number(followerUserId));
  req.setBeFollowed(jsTimestampToPb(beFollowed));
  req.setAliasName(aliasName);

  return new Promise((resolve, reject) => {
    cl.upsertStoreFan(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(StoreFanPbToObject(res.getStoreFan()!));
    });
  });
};

export const updateStoreFan = async ({
  storeFanId,
  aliasName,
  remark,
}: UpdateStoreFanParams): Promise<StoreFan> => {
  const cl = getBgsStoreFanOpSafely();
  const req = new store_fanpb.UpdateStoreFanRequest();

  req.setId(Number(storeFanId));
  req.setAliasName(aliasName);
  if (!isUndefined(remark)) {
    req.setRemark(remark);
  }

  return new Promise((resolve, reject) => {
    cl.updateStoreFan(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(StoreFanPbToObject(res.getStoreFan()!));
    });
  });
};

/****************************************************************************************/
/*                                   store_fan query                                    */
/****************************************************************************************/

export const getStoreFan = async (storeFanId: string): Promise<StoreFan> => {
  const cl = getBgsStoreFanOpSafely();
  const req = new store_fanpb.GetStoreFanRequest();

  req.setId(Number(storeFanId));

  return new Promise((resolve, reject) => {
    cl.getStoreFan(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(StoreFanPbToObject(res.getStoreFan()!));
    });
  });
};

/****************************************************************************************/
/*                                   store_fan joins entity                             */
/****************************************************************************************/

const storeFanWithUserAndUserStatPbToObject = (
  pb: store_fanpb.StoreFanWithUserAndUserStatEntity
): StoreFanWithUserAndUserStat => {
  return {
    // store_fan
    storeFanId: `${pb.getId()}`,
    storeId: `${pb.getStoreId()}`,
    followerUserId: `${pb.getFollowerUserId()}`,
    beFollowed: pbTimestampToJs(pb.getBeFollowed()),
    aliasName: pb.getAliasName(),
    remark: pb.getRemark(),
    // user
    followerUserNickName: pb.getFollowerUserNickName(),
    followerUserPic: pb.getFollowerUserPic(),
    // user_stat
    fansCount: pb.getFansCount(),
    followUserCount: pb.getFollowUserCount(),
    followBrandCount: pb.getFollowBrandCount(),
    followStoreCount: pb.getFollowStoreCount(),
    endorseBrandCount: pb.getEndorseBrandCount(),
    endorseStoreCount: pb.getEndorseStoreCount(),
    endorseActivityCount: pb.getEndorseActivityCount(),
    involveActivityCount: pb.getInvolveActivityCount(),
    orderCount: pb.getOrderCount(),
    viewCount: pb.getViewCount(),
    payAmount: pb.getPayAmount(),
  };
};

export interface ListStoreFanWithUserAndUserStatsParam {
  storeId: string;
  keyword?: string;
}

export const listStoreFanWithUserAndUserStats = async (
  { storeId, keyword }: ListStoreFanWithUserAndUserStatsParam,
  pager: PageParams
): Promise<PagedList<StoreFanWithUserAndUserStat>> => {
  const cl = getBgsStoreFanOpSafely();
  const req = new store_fanpb.ListStoreFanWithUserAndUserStatsRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setTs(jsTimestampToPb(pager.ts));
  req.setStoreId(Number(storeId));
  if (!isUndefined(keyword)) {
    req.setKeyword(keyword);
  }

  return new Promise((resolve, reject) => {
    cl.listStoreFanWithUserAndUserStats(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<StoreFanWithUserAndUserStat> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res
          .getStoreFanWithUserStatsList()
          .map((u) => storeFanWithUserAndUserStatPbToObject(u));
        resolve(ret);
      }
    );
  });
};
